home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
429_01
/
chess12
/
chess.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-29
|
28KB
|
1,252 lines
#include "misc.hpp"
#include "brdsize.hpp"
#include "chess.hpp"
extern void OutOfMemory(void);
// piece values.
const int VALUEKING = 0,
VALUEPAWN = 2,
VALUEROOK = 10,
VALUEKNIGHT = 6,
VALUEBISHOP = 6,
VALUEQUEEN = 18;
class PAWN : public PIECE
{
private:
// pointer to piece to which pawn has been promoted. null if
// pawn has not been promoted.
PIECE *promotePiece;
public:
PAWN(PIECECOLOR c) : PIECE(c, TYPEPAWN, VALUEPAWN), promotePiece(0) { }
virtual ~PAWN(void) { if (promotePiece) delete promotePiece; }
void promote(PIECETYPE promoteType);
void restoreToPawn(void);
virtual PIECETYPE whatType(void) const
{
if (promotePiece)
return(promotePiece->whatType());
else
return(PIECE::whatType());
}
virtual int whatValue(void) const
{
if (promotePiece)
return(promotePiece->whatValue());
else
return(PIECE::whatValue());
}
virtual void legalMoves
(
POSITION start,
const BOARD &board,
POSITIONLIST &moves
) const;
};
class ROOK : public PIECE
{
public:
ROOK(PIECECOLOR c) : PIECE(c, TYPEROOK, VALUEROOK) { }
virtual void legalMoves
(
POSITION start,
const BOARD &board,
POSITIONLIST &moves
) const;
};
class KNIGHT : public PIECE
{
public:
KNIGHT(PIECECOLOR c) : PIECE(c, TYPEKNIGHT, VALUEKNIGHT) { }
virtual void legalMoves
(
POSITION start,
const BOARD &board,
POSITIONLIST &moves
) const;
};
class BISHOP : public PIECE
{
public:
BISHOP(PIECECOLOR c) : PIECE(c, TYPEBISHOP, VALUEBISHOP) { }
virtual void legalMoves
(
POSITION start,
const BOARD &board,
POSITIONLIST &moves
) const;
};
class QUEEN : public PIECE
{
public:
QUEEN(PIECECOLOR c) : PIECE(c, TYPEQUEEN, VALUEQUEEN) { }
virtual void legalMoves
(
POSITION start,
const BOARD &board,
POSITIONLIST &moves
) const;
};
class KING : public PIECE
{
public:
KING(PIECECOLOR c) : PIECE(c, TYPEKING, VALUEKING) { }
virtual void legalMoves
(
POSITION start,
const BOARD &board,
POSITIONLIST &moves
) const;
};
// put all the pieces for one color at their starting positions on
// the board
LOCAL void setupPieces
(
PIECE *board[][NUMCOLS],
PIECECOLOR color,
// column in which the non-pawn pieces go
int backCol,
// column in which the pawns go
int pawnCol
)
{
BOOL f = TRUE;
int row;
#define NEWPIECE(P, ROWOFFSET, COLOFFSET) \
f = f && \
((board[ROWOFFSET][COLOFFSET] = new P) != (PIECE *) 0);
NEWPIECE(ROOK(color), 0, backCol);
NEWPIECE(KNIGHT(color), 1, backCol);
NEWPIECE(BISHOP(color), 2, backCol);
NEWPIECE(QUEEN(color), 3, backCol);
NEWPIECE(KING(color), 4, backCol);
NEWPIECE(BISHOP(color), 5, backCol);
NEWPIECE(KNIGHT(color), 6, backCol);
NEWPIECE(ROOK(color), 7, backCol);
for (row = 0; row < NUMROWS; row++)
NEWPIECE(PAWN(color), row, pawnCol);
if (!f)
OutOfMemory();
return;
#undef NEWPIECE
}
BOARD::BOARD(void)
{
int row, col;
for (row = 0; row < NUMROWS; row++)
for (col = 0; col < NUMCOLS; col++)
brd[row][col] = (PIECE *) 0;
setupPieces(brd, WHITE, 0, 1);
setupPieces(brd, BLACK, 7, 6);
wasLastMoveDoublePawn = FALSE;
return;
}
BOARD::~BOARD(void)
{
int r, c;
for (r = 0; r < NUMROWS; r++)
for (c = 0; c < NUMROWS; c++)
{
if (brd[r][c])
delete brd[r][c];
}
return;
}
void BOARD::doMove
(
POSITION start,
POSITION end,
MOVEUNDODATA &undoData
)
{
undoData.capturedPiece = brd[end.row][end.col];
undoData.enPassantEffect = OTHERMOVE;
brd[end.row][end.col] = brd[start.row][start.col];
brd[start.row][start.col] = (PIECE *) 0;
brd[end.row][end.col]->moveDone();
if (brd[end.row][end.col]->whatType() == TYPEPAWN)
{
if (wasLastMoveDoublePawn)
if ((doubleMovedPawn.row == end.row) &&
(doubleMovedPawn.col == start.col) &&
(start.row != end.row) &&
!undoData.capturedPiece)
// these last two tests are necessary to handle situations
// where the same color is moved twice in a row when
// looking for check in "canCastle" and looking for
// stalemate
{
// en passant capture
undoData.capturedPiece =
brd[doubleMovedPawn.row][doubleMovedPawn.col];
brd[doubleMovedPawn.row][doubleMovedPawn.col] =
(PIECE *) 0;
undoData.saveDoubleMoved = doubleMovedPawn;
undoData.enPassantEffect = ENPASSANTCAPTURE;
wasLastMoveDoublePawn = FALSE;
return;
}
{
int diff = start.col - end.col;
if (diff < 0)
diff = -diff;
if (diff == 2)
{
if (wasLastMoveDoublePawn)
{
undoData.saveDoubleMoved = doubleMovedPawn;
undoData.enPassantEffect = AFTERDOUBLEMOVE;
}
doubleMovedPawn = end;
wasLastMoveDoublePawn = TRUE;
return;
}
}
}
if (wasLastMoveDoublePawn)
{
undoData.saveDoubleMoved = doubleMovedPawn;
undoData.enPassantEffect = AFTERDOUBLEMOVE;
}
wasLastMoveDoublePawn = FALSE;
return;
}
void BOARD::undoMove
(
POSITION end,
POSITION orig,
MOVEUNDODATA undoData
)
{
brd[orig.row][orig.col] = brd[end.row][end.col];
brd[orig.row][orig.col]->moveUndone();
if (undoData.enPassantEffect == ENPASSANTCAPTURE)
{
brd[end.row][orig.col] = undoData.capturedPiece;
brd[end.row][end.col] = (PIECE *) 0;
}
else
brd[end.row][end.col] = undoData.capturedPiece;
if (undoData.enPassantEffect == OTHERMOVE)
wasLastMoveDoublePawn = FALSE;
else
{
wasLastMoveDoublePawn = TRUE;
doubleMovedPawn = undoData.saveDoubleMoved;
}
return;
}
BOOL BOARD::canCastle(MOVETYPE whichCastle, PIECECOLOR color)
{
int col = color == WHITE ? 0 : 7;
int row, rowStep;
BOARDMETRIC metric;
if (whichCastle == QUEENSIDECASTLE)
{
row = 0;
rowStep = 1;
}
else
{
row = 7;
rowStep = -1;
}
// make sure king & rook in initial positions and have never been
// moved.
if (!brd[row][col])
return(FALSE);
if (brd[row][col]->hasBeenMoved())
return(FALSE);
if (!brd[4][col])
return(FALSE);
if (brd[4][col]->hasBeenMoved())
return(FALSE);
// make sure no pieces in between
for ( ; ; )
{
row += rowStep;
if (row == 4)
break;
if (brd[row][col])
return(FALSE);
}
// make sure king is not in check
findBestMoves(1, OtherColor(color), metric, (BESTMOVES *) 0);
if (metric.kingSituation[color] == KINGLOST)
return(FALSE);
// make sure king would not be in check in intermediate position
brd[4 - rowStep][col] = brd[4][col];
brd[4][col] = (PIECE *) 0;
findBestMoves(1, OtherColor(color), metric, (BESTMOVES *) 0);
brd[4][col] = brd[4 - rowStep][col];
brd[4 - rowStep][col] = (PIECE *) 0;
return(metric.kingSituation[color] == KINGOK);
}
void BOARD::castle
(
MOVETYPE whichCastle,
PIECECOLOR color,
MOVEUNDODATA &undoData
)
{
int col = color == WHITE ? 0 : 7;
if (whichCastle == QUEENSIDECASTLE)
{
brd[3][col] = brd[0][col];
brd[2][col] = brd[4][col];
brd[0][col] = (PIECE *) 0;
brd[4][col] = (PIECE *) 0;
brd[3][col]->moveDone();
brd[2][col]->moveDone();
}
else
{
brd[5][col] = brd[7][col];
brd[6][col] = brd[4][col];
brd[7][col] = (PIECE *) 0;
brd[4][col] = (PIECE *) 0;
brd[5][col]->moveDone();
brd[6][col]->moveDone();
}
if (wasLastMoveDoublePawn)
{
undoData.enPassantEffect = AFTERDOUBLEMOVE;
undoData.saveDoubleMoved = doubleMovedPawn;
wasLastMoveDoublePawn = FALSE;